﻿using CIS.DB;
using CIS.Web.Common;
using CIS.Web.Models;
using CIS.Web.Properties;
using System;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace CIS.Web.Controllers
{
	[RoutePrefix("ConferenceHotelEdit")]
	public class ConferenceHotelEditController : BaseDbController
	{
		[Route("Index/{ConferenceId}")]
		public async Task<ActionResult> Index(string conferenceId)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", conferenceId);

			var conferenceMaster = await DbContext.ConferenceMaster.AsNoTracking()
					.FirstOrDefaultAsync(x => x.Status == ConstValues.Status.正常 &&
						x.ID == conferenceId);

			ViewBag.ConferenceId = conferenceId;
			ViewBag.ConferenceName = conferenceMaster.ConferenceName;
			ViewBag.ControllerName = Resources.ConferenceHotelEdit;
			ViewBag.Language = conferenceMaster.IsInternational ? ConstValues.Language.En : ConstValues.Language.Cn;

			var model = new ConferenceHotelEditModel();
			model.ConferenceId = conferenceId;
			LoginUser.ConferenceFunctionIdList = Utility.GetConferenceFunctionIdList(conferenceId);
			return View(model);
		}

		public async Task<JsonCamelCaseResult> GetData(int? page, int? rows, string sort, string order, ConferenceHotelEditModel model)
		{
			int take = rows ?? ConstValues.DefaultGridRows;
			int skip = ((page ?? 1) - 1) * take;

			var sql = DbContext.HotelMaster.AsNoTracking()
					.Where(x => !string.IsNullOrEmpty(x.Status) && x.ConferenceId == model.ConferenceId);
			
			if (!string.IsNullOrWhiteSpace(model.SearchHotelName) && model.SearchHotelName != "")
			{
				sql = sql.Where(x => x.HotelName.Contains(model.SearchHotelName));
			}
			int total = await sql.CountAsync();
			if (!string.IsNullOrEmpty(sort))
			{
				sql = sql.OrderBy(sort + ConstValues.chrSpace + order).Skip(skip).Take(take);
			}
			else
			{
				sql = sql.OrderBy(x => x.Sort).ThenByDescending(x => x.UpdateDate).ThenBy(x => x.HotelName).Skip(skip).Take(take);
			}

			var sqlResult = await sql.ToListAsync();

			var result = sqlResult.Select(x => new
			{
				ID = x.ID,
				HotelName = x.HotelName,
				HotelAddress = x.HotelAddress,
				HotelTel = x.HotelTel,
				Level = x.Level,
				ParkingFee = x.ParkingFee,
				//TotalBedCount = x.TotalBedCount,
				//TotalRoomCount = x.TotalRoomCount,
				//LeftBedCount = x.LeftBedCount,
				//LeftRoomCount = x.LeftRoomCount,
				Status = x.Status,
				Sort = x.Sort,
				Remark = x.Remark,
				Creator = x.Creator,
				CreateIP = x.CreateIP,
				CreateDate = Request.Cookies["_culture"].Value == ConstValues.Language.Cn ?
					x.CreateDate.Value.ToString("yyyy-MM-dd") :
					x.CreateDate.Value.ToString("MM/dd/yyyy")
			});

			return JsonCamelCase(new
			{
				Total = total,
				Rows = result,
			},
			JsonRequestBehavior.AllowGet);
		}

		public async Task<JsonCamelCaseResult> GetEditData(string id)
		{
			var data = await DbContext.HotelMaster.AsNoTracking().FirstOrDefaultAsync(x => x.ID == id);
			if (data != null)
			{
				var result = new
				{
					parkFee = data.ParkingFee,
					leftBedCount = data.LeftBedCount,
					leftRoomCount = data.LeftRoomCount,
					totalRoomCount = data.TotalRoomCount,
					totalBedCount = data.TotalBedCount,
					address = data.HotelAddress,
					hotelName = data.HotelName,
					hotelTel = data.HotelTel,
					starLevel = data.Level,

					sort = data.Sort,
					status = data.Status,
					remark = data.Remark
				};

				return JsonCamelCase(Utility.CreateSuccessJsonResult(string.Empty, result),
						JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("Create/{ConferenceId}")]
		public async Task<JsonResult> Create(ConferenceHotelEditModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			var result = await DbContext.HotelMaster
					.FirstOrDefaultAsync(x => x.ConferenceId == model.ConferenceId &&
						x.HotelName == model.hotelName);

			if (result != null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(
					string.Format(Resources.MsgRecordExist, Resources.HotelName)),
					JsonRequestBehavior.AllowGet);
			}

			var hotelMaster = new HotelMaster
			{
				ID = Utility.GetTableId(ConstValues.TableName.HotelMaster),
				HotelTel = model.telephone?.Trim(),
				HotelAddress = model.address?.Trim(),
				HotelName = model.hotelName?.Trim(),
				Level = model.starLevel,
				ParkingFee = model.parkFee,
				LeftBedCount = ConstValues.intZero,
				LeftRoomCount = ConstValues.intZero,
				TotalBedCount = ConstValues.intZero,
				TotalRoomCount = ConstValues.intZero,

				ConferenceId = model.ConferenceId,
				Status = model.Status,
				Sort = model.Sort.HasValue ? model.Sort.Value : ConstValues.DefaultSort,
				Remark = model.Remark?.Trim(),
				Creator = LoginUser.UserName,
				CreateIP = LoginUser.IP,
				CreateDate = DateTime.Now
			};

			DbContext.HotelMaster.Add(hotelMaster);
			await DbContext.SaveChangesAsync();

			return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit),
					JsonRequestBehavior.AllowGet);
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("CreateRoom/{ConferenceId}")]
		public async Task<JsonResult> CreateRoom(ConferenceHotelEditModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			var result = await DbContext.RoomMaster.AsNoTracking()
					.FirstOrDefaultAsync(x => x.HotelId == model.HotelID &&
						x.RoomType == model.RoomType &&
						x.Currency == model.RoomCurrency &&
						x.BookDate == model.BookingDate);

			if (result != null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(
						string.Format(Resources.MsgRoomTypeIsExist)),
						JsonRequestBehavior.AllowGet);
			}

			var roomMaster = new RoomMaster
			{
				ID = Utility.GetTableId(ConstValues.TableName.RoomMaster),
				HotelId = model.HotelID,
				RoomType = model.RoomType,
				RoomBedCount = model.RoomTypeBedNum,
				LeftBedCount = model.RoomTotalRoomCount * model.RoomTypeBedNum,
				LeftRoomCount = model.RoomTotalRoomCount,
				TotalBedCount = model.RoomTotalRoomCount * model.RoomTypeBedNum,
				TotalRoomCount = model.RoomTotalRoomCount,
				Price1 = model.RoomPrice1,
				Price2 = model.RoomPrice2,
				Currency = model.RoomCurrency,
				BookDate = model.BookingDate,
				Status = model.RoomStatus,
				Sort = model.RoomSort.HasValue ? model.RoomSort.Value : ConstValues.DefaultSort,
				Remark = model.RoomRemark?.Trim(),
				Creator = LoginUser.UserName,
				CreateIP = LoginUser.IP,
				CreateDate = DateTime.Now
			};

			DbContext.RoomMaster.Add(roomMaster);

			await DbContext.SaveChangesAsync();
			return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit),
					JsonRequestBehavior.AllowGet);
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("Modify/{ConferenceId}")]
		public async Task<JsonResult> Modify(ConferenceHotelEditModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			var exist = await DbContext.HotelMaster.AsNoTracking()
					.FirstOrDefaultAsync(x => x.ID != model.Id &&
						x.ConferenceId == model.ConferenceId &&
						x.HotelName == model.hotelName);

			if (exist != null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(
						string.Format(Resources.MsgRecordExist, Resources.HotelName)),
						JsonRequestBehavior.AllowGet);
			}

			var existInfo = await DbContext.ProfileHotelInfo.AsNoTracking()
					.Where(x => x.HotelId == model.Id).ToListAsync();

			if (existInfo.Count > 0)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgUsingCanNotChange),
						JsonRequestBehavior.AllowGet);
			}

			var result = await DbContext.HotelMaster.FirstOrDefaultAsync(x => x.ID == model.Id);

			if (result != null)
			{
				result.HotelTel = model.telephone?.Trim();
				result.HotelAddress = model.address?.Trim();
				result.HotelName = model.hotelName?.Trim();
				result.Level = model.starLevel;
				result.ParkingFee = model.parkFee;

				result.Sort = model.Sort.HasValue ? model.Sort.Value : ConstValues.DefaultSort;
				result.Remark = model.Remark?.Trim();
				result.Status = model.Status;

				result.Updater = LoginUser.UserName;
				result.UpdateDate = DateTime.Now;
				result.UpdateIP = LoginUser.IP;

				await DbContext.SaveChangesAsync();

				return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit),
						JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("ModifyRoom/{ConferenceId}")]
		public async Task<JsonResult> ModifyRoom(ConferenceHotelEditModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);
			
			var exist = await DbContext.RoomMaster.AsNoTracking()
					.FirstOrDefaultAsync(x => x.ID != model.RoomID &&
						x.RoomType == model.RoomType &&
						x.Currency == model.RoomCurrency &&
						x.HotelId == model.HotelID &&
						x.BookDate == model.BookingDate);

			if (exist != null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(
						string.Format(Resources.MsgRecordExist, Resources.RoomType)),
						JsonRequestBehavior.AllowGet);
			}

			int? changeTotalNum;
			var result = await DbContext.RoomMaster.FirstOrDefaultAsync(x => x.ID == model.RoomID);

			var needModify = false;
			var oldRoomType = "";
			if (result != null)
			{
				int usingRoom = result.TotalRoomCount.Value - result.LeftRoomCount.Value;
				if (model.RoomTotalRoomCount >= usingRoom)
				{
					using (var transaction = DbContext.Database.BeginTransaction())
					{
						var existInfo = await DbContext.ProfileHotelInfo.AsNoTracking()
								.Where(x => x.RoomId == model.RoomID).ToListAsync();

						//若某天某房型的价格没有被选择
						if (existInfo.Count == 0)
						{
							result.Price2 = model.RoomPrice2;
							result.Price1 = model.RoomPrice1;
							result.BookDate = model.BookingDate;
							result.Status = model.RoomStatus;
							result.Currency = model.RoomCurrency;
						}
						else
						{
							//若某天某房型的价格已被选择，酒店信息设置中该天该房型的价格、日期、币种、状态不能被修改
							if (result.Price1 != model.RoomPrice1 ||
								result.Price2 != model.RoomPrice2 ||
								result.BookDate != model.BookingDate ||
								result.Status != model.RoomStatus  ||
								result.Currency != model.RoomCurrency)
							{
								return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgUsingCanNotChange),
										JsonRequestBehavior.AllowGet);
							}
						}

						changeTotalNum = model.RoomTotalRoomCount - result.TotalRoomCount;

						//如果修改了房间类型，就要把profileHotelInfo表对应的房间类型全部改掉
						if (result.RoomType != model.RoomType?.Trim())
						{
							oldRoomType = result.RoomType;
							needModify = true;
						}
						result.RoomType = model.RoomType?.Trim();
						//result.RoomBedCount = model.RoomTypeBedNum;
						result.LeftBedCount = result.LeftBedCount + changeTotalNum * result.RoomBedCount;
						result.TotalRoomCount = model.RoomTotalRoomCount;
						result.LeftRoomCount = result.LeftRoomCount + changeTotalNum;
						result.TotalBedCount = model.RoomTotalRoomCount * result.RoomBedCount;
					
						result.Sort = model.RoomSort.HasValue ? model.RoomSort.Value : ConstValues.DefaultSort;
						result.Remark = model.RoomRemark?.Trim();
					
						result.Updater = LoginUser.UserName;
						result.UpdateDate = DateTime.Now;
						result.UpdateIP = LoginUser.IP;

						if (needModify)
						{
							var oldRoomMaster = DbContext.RoomMaster.Where(x => x.HotelId == result.HotelId && x.RoomType == oldRoomType).ToList();
							foreach (var y in oldRoomMaster)
							{
								y.RoomType = model.RoomType?.Trim();
								y.Updater = LoginUser.UserName;
								y.UpdateDate = DateTime.Now;
								y.UpdateIP = LoginUser.IP;
							}

							var profileHotelInfo = DbContext.ProfileHotelInfo.Where(x => x.HotelId == result.HotelId && x.RoomType == oldRoomType).ToList();
							foreach (var y in profileHotelInfo)
							{
								y.RoomType = model.RoomType?.Trim();
							}
						}
						await DbContext.SaveChangesAsync();
						transaction.Commit();
					}

					return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit), JsonRequestBehavior.AllowGet);
				}
				else
				{
					return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgTotalRoomTooLittle),
							JsonRequestBehavior.AllowGet);
				}
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("Delete/{ConferenceId}")]
		public async Task<JsonResult> Delete(ConferenceHotelEditModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			var existInfo = await DbContext.ProfileHotelInfo.AsNoTracking()
					.Where(x => x.HotelId == model.Id).ToListAsync();

			if (existInfo.Count > 0)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgUsingCanNotDelete),
						JsonRequestBehavior.AllowGet);
			}

			var hotelMaster = await DbContext.HotelMaster.FirstOrDefaultAsync(x => x.ID == model.Id);

			if (hotelMaster != null)
			{
				var roomMaster = await DbContext.RoomMaster.Where(x => x.HotelId == model.Id).ToListAsync();
				DbContext.RoomMaster.RemoveRange(roomMaster);
				DbContext.HotelMaster.Remove(hotelMaster);
				await DbContext.SaveChangesAsync();

				return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessDelete),
					JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("DeleteRoom/{ConferenceId}")]
		public async Task<JsonResult> DeleteRoom(ConferenceHotelEditModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			var existInfo = await DbContext.ProfileHotelInfo.AsNoTracking()
					.Where(x => x.RoomId == model.RoomID).ToListAsync();

			if (existInfo.Count > 0)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgUsingCanNotDelete),
						JsonRequestBehavior.AllowGet);
			}

			var roomMaster = await DbContext.RoomMaster.FirstOrDefaultAsync(x => x.ID == model.RoomID);

			if (roomMaster != null)
			{
				var hotelMaster = await DbContext.HotelMaster.FirstOrDefaultAsync(x => x.ID == model.HotelID);
				hotelMaster.LeftBedCount = hotelMaster.LeftBedCount - roomMaster.TotalBedCount;
				hotelMaster.TotalBedCount = hotelMaster.TotalBedCount - roomMaster.TotalBedCount;
				hotelMaster.LeftRoomCount = hotelMaster.LeftRoomCount - roomMaster.TotalRoomCount;
				hotelMaster.TotalRoomCount = hotelMaster.TotalRoomCount - roomMaster.TotalRoomCount;
				hotelMaster.Updater = LoginUser.UserName;
				hotelMaster.UpdateDate = DateTime.Now;
				hotelMaster.UpdateIP = LoginUser.IP;

				DbContext.RoomMaster.Remove(roomMaster);

				await DbContext.SaveChangesAsync();

				return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessDelete),
					JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
					JsonRequestBehavior.AllowGet);
			}
		}

		public async Task<JsonCamelCaseResult> GetRoomData(string hotelId)
		{
			var sql = DbContext.RoomMaster.AsNoTracking()
					.Where(x => x.HotelId == hotelId)
					.OrderBy(x => x.Sort)
					.ThenByDescending(x => x.UpdateDate)
					.ThenBy(x => x.RoomType)
					.ThenBy(x => x.BookDate);

			int total = await sql.CountAsync();

			var sqlResult = await sql.ToListAsync();

			var result = sqlResult.Select(x => new
			{
				ID = x.ID,
				RoomType = x.RoomType,
				RoomBedCount = x.RoomBedCount,
				Price1 = x.Price1.HasValue ? x.Price1.Value.ToString("N2") : string.Empty,
				Price2 = x.Price2.HasValue ? x.Price2.Value.ToString("N2") : string.Empty,
				Currency = x.Currency,
				TotalBedCount = x.TotalBedCount,
				TotalRoomCount = x.TotalRoomCount,
				LeftBedCount = x.LeftBedCount,
				LeftRoomCount = x.LeftRoomCount,
				BookDate = Request.Cookies["_culture"].Value == ConstValues.Language.Cn ?
						x.BookDate.Value.ToString("yyyy-MM-dd") :
						x.BookDate.Value.ToString("MM/dd/yyyy"),
				Status = x.Status,
				Sort = x.Sort,
				Remark = x.Remark,
				Creator = x.Creator,
				CreateIP = x.CreateIP,
				CreateDate = Request.Cookies["_culture"].Value == ConstValues.Language.Cn ?
						x.CreateDate.Value.ToString("yyyy-MM-dd") :
						x.CreateDate.Value.ToString("MM/dd/yyyy")
			});

			return JsonCamelCase(new
			{
				Total = total,
				Rows = result,
			},
			JsonRequestBehavior.AllowGet);
		}

		public async Task<JsonCamelCaseResult> GetRoomEditData(string id)
		{
			var data = await DbContext.RoomMaster.AsNoTracking().FirstOrDefaultAsync(x => x.ID == id);
			if (data != null)
			{
				var result = new
				{
					roomType = data.RoomType,
					roomBedCount = data.RoomBedCount,
					currency = data.Currency,
					price1 = data.Price1,
					price2 = data.Price2,
					leftRoomCount = data.LeftRoomCount,
					totalRoomCount = data.TotalRoomCount,
					bookDate = Request.Cookies["_culture"].Value == ConstValues.Language.Cn ?
						data.BookDate.Value.ToString("yyyy-MM-dd") :
						data.BookDate.Value.ToString("MM/dd/yyyy"),
					sort = data.Sort,
					status = data.Status,
					remark = data.Remark
				};
				return JsonCamelCase(Utility.CreateSuccessJsonResult(string.Empty, result),
					JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
					JsonRequestBehavior.AllowGet);
			}
		}
	}
}